package container

import (
	"codejy/analysis"
	"codejy/globalfunc"
	"codejy/store"
	"codejy/structdef"
	"codejy/typedefault"
	"codejy/utils"
	"fmt"
	"strconv"
	"strings"
)

type TypeList struct {
	Addr        string
	ThreadStore *structdef.ThreadStore
	List        []string
	NextIndex   int
}

// 创建实例
func (a *TypeList) CreateTypeDefault(addr string, threadStore *structdef.ThreadStore, parameter ...string) {
	list := &TypeList{
		Addr:        addr,
		ThreadStore: threadStore,
		List:        []string{},
		NextIndex:   0,
	}
	store.AddTypeDefaultInstanceStore(threadStore, a.GetTypeName(), addr, list)
}
func (a *TypeList) GetData() interface{} {
	return a.List
}
func (a *TypeList) ToStr() string {
	var Str string
	//如果是List,那么打印出来
	value, b := typedefault.GetTypeDefaultValue[[]string](a.ThreadStore, a.GetTypeName(), a.Addr)
	if b {
		Str = "["
		//以逗号分隔
		for _, v := range value {
			//判断是否是字符串
			Str += analysis.AddDoubleQuotationMarks(v) + ","
		}
		Str = Str[:len(Str)-1]
		Str += "]"
		return a.GetTypeName() + ":" + Str
	}
	return ""
}

func (a *TypeList) ParameterProcessing(parameter []string) []string {
	return parameter
}

// 添加数据
func (a *TypeList) AddList(value string) {
	a.List = append(a.List, value)
}

// 通过下标修改数据
func (a *TypeList) UpdateList(index string, value string) {
	atoi, _ := strconv.Atoi(index)
	if atoi < 0 || atoi >= len(a.List) {
		panic("index out of range")
	}
	a.List[atoi] = value
}

// 通过下标删除数据
func (a *TypeList) DeleteList(index string) {
	atoi, _ := strconv.Atoi(index)
	if atoi < 0 || atoi >= len(a.List) {
		panic("index out of range")
	}
	a.List = append(a.List[:atoi], a.List[atoi+1:]...)
}

// 通过下标获取数据
func (a *TypeList) GetList(index string) string {
	atoi, _ := strconv.Atoi(index)
	if atoi < 0 || atoi >= len(a.List) {
		panic("索引超出范围")
	}
	return a.List[atoi]
}

// 获取数量
func (a *TypeList) GetListCount() string {
	count := len(a.List)
	return strconv.Itoa(count)
}

// 截取范围数据
func (a *TypeList) SubRange(startIndex, endIndex string) string {
	if startIndex != "" && endIndex == "" {
		start, _ := strconv.Atoi(startIndex)
		if start < 0 || start >= len(a.List) {
			panic("起始索引超出范围")
		}
		slice := a.List[start:]
		return SliceToList(slice, a.ThreadStore)
	}
	if startIndex != "" && endIndex != "" {
		start, _ := strconv.Atoi(startIndex)
		end, _ := strconv.Atoi(endIndex)
		if start < 0 || start >= len(a.List) || end < 0 || end >= len(a.List) {
			panic("起始或结束索引超出范围")
		}
		slice := a.List[start:end]
		return SliceToList(slice, a.ThreadStore)
	}
	panic("参数错误,起始索引不能为空")
}

// 排序,从小到大,只支持数字,字符串
func (a *TypeList) SortList() {
	//判断第一个元素是否为数字
	_, err := strconv.Atoi(a.List[0])
	if err != nil {
		utils.SortSlice[string](&a.List, 0, func(a, b string) int {
			return len(a) - len(b)
		})
	} else {
		utils.SortSlice[string](&a.List, 0, func(a, b string) int {
			atoi, _ := strconv.Atoi(a)
			atoi2, _ := strconv.Atoi(b)
			return atoi - atoi2
		})
	}
}

// List字符串去重,优先删除后面的重复的
func (a *TypeList) RepeatList() {
	utils.RemoveDuplicate[string](&a.List, 1, func(a, b string) bool {
		return a == b
	})
}

// 合并List到当前List,不去重
func (a *TypeList) MergeList(list string) string {
	value, b := typedefault.GetTypeDefaultValue[[]string](a.ThreadStore, a.GetTypeName(), list)
	if !b {
		panic("需要合并的list不存在")
	}
	var slice []string
	slice = append(slice, a.List...)
	slice = append(slice, value...)
	return SliceToList(slice, a.ThreadStore)
}

// 并集,合并两个切片,去重
func (a *TypeList) UnionList(list string) string {

	value, b := typedefault.GetTypeDefaultValue[[]string](a.ThreadStore, a.GetTypeName(), list)
	if !b {
		panic("需要并集的list不存在")
	}
	slice := utils.UnionSlice[string](&a.List, &value, func(a, b string) bool {
		return a == b
	})
	return SliceToList(*slice, a.ThreadStore)
}

// 交集,两个切片中相同的元素
func (a *TypeList) IntersectList(list string) string {
	value, b := typedefault.GetTypeDefaultValue[[]string](a.ThreadStore, a.GetTypeName(), list)
	if !b {
		panic("需要交集的list不存在")
	}
	slice := utils.IntersectSlice[string](&a.List, &value, func(a, b string) bool {
		return a == b
	})
	return SliceToList(*slice, a.ThreadStore)
}

// 差集,两个切片中不同的元素
func (a *TypeList) DifferenceList(list string) string {
	value, b := typedefault.GetTypeDefaultValue[[]string](a.ThreadStore, a.GetTypeName(), list)
	if !b {
		panic("差集交集的list不存在")
	}
	slice := utils.DifferenceSlice[string](&a.List, &value, func(a, b string) bool {
		return a == b
	})
	return SliceToList(*slice, a.ThreadStore)
}

// 复制List
func (a *TypeList) CopyList() string {
	slice := make([]string, len(a.List))
	for i, v := range a.List {
		slice[i] = v
	}
	return SliceToList(slice, a.ThreadStore)
}

// 每次迭代一个元素
func (a *TypeList) Next() string {
	if a.NextIndex >= len(a.List) {
		a.NextIndex = 0
		return "" //迭代完毕
	}
	value := a.List[a.NextIndex]
	sprintf := fmt.Sprintf("%d,%s", a.NextIndex, value)
	a.NextIndex++
	return sprintf
}

// List转多行字符串
func (a *TypeList) ToMultiLine() string {
	return strings.Join(a.List, "\n")
}

func (a *TypeList) GetDef() string {
	return `
		@CodeManual(def="new("List")",des="创建List容器")
		type  List{
			def init{
				core&CreateTypeDefault()
			}
			
			@CodeManual(def="add($1)",des="添加数据,例:list.add("123")")
			def add{
				core&AddList($1)
			}


			@CodeManual(def="set($1,$2)",des="修改数据,例:list.set(1,"2")")
			def set{
				core&UpdateList($1,$2)
			}

			@CodeManual(def="del($1)",des="删除数据,例:list.del(1)")
			def del{
				core&DeleteList($1)	
			} 

			@CodeManual(def="get($1)",des="获取数据,例:list.get(1)")
			def get{
				to core&GetList($1)	
			}
		

			@CodeManual(def="size()",des="获取数量,例:list.size()")
			def size{
				to core&GetListCount()
			}		

			@CodeManual(def="range($1,$2)",des="截取List返回新的List(起始下标从0开始, 结束下标从1开始)(返回新List),例:list.range(1,3)")
			def range{
				to core&SubRange($1,$2)
			}
			//根据第一个数据来判断是否是字符串长度排序,还是数字大小排序
			@CodeManual(def="sort()",des="排序(作用自己),例:list.sort()")
			def sort{
				core&SortList()
			}
			//去重会优先删除后面重复的
			@CodeManual(def="repeat()",des="去重(作用自己),例:list.repeat()")
			def repeat{
				core&RepeatList()
			}
			@CodeManual(def="merge($1)",des="合并(不去重)(返回新List),例:list.merge(list2)")
			def merge{
				to core&MergeList($1)
			}

			@CodeManual(def="union($1)",des="并集(去重)(返回新List),例:list.union(list2)")
			def union{
				to core&UnionList($1)
			}

			@CodeManual(def="intersect($1)",des="交集(返回新List),例:list.intersect(list2)")
			def intersect{
				to core&IntersectList($1)
			}

			@CodeManual(def="difference($1)",des="差集(返回新List),例:list.difference(list2)")
			def difference{
				to core&DifferenceList($1)
			}
			//这个是浅拷贝,如果存储的是实例,那么复制的就是实例的地址而不是实例本身数据
			//也就是说,如果修改复制的实例,那么原来的实例也会被修改
			@CodeManual(def="copy()",des="复制自己返回新List(浅拷贝),例:list.copy()")
			def copy{
				to core&CopyList()
			}
			@CodeManual(def="toMultiLine()",des="转多行字符串,每行字符串结尾是\n, 例:list.toMultiLine()")
			def toMultiLine{
				to core&ToMultiLine()
			}

			def toStr{
				to core&ToStr()
			}
			def next{
				to core&Next()
			}

		}
	`
}

func init() {
	typedefault.RegisterTypeDefault(&TypeList{})
	globalfunc.RegisterFuncAll("SliceToList", SliceToList)
}

func (a *TypeList) GetTypeName() string {
	return "List"
}

// 将go语言分片数据转换为简易实例List (内部方法,不对外暴露)
func SliceToList(list []string, threadStore *structdef.ThreadStore) string {
	addr := typedefault.TypeDefaultNewInstance("List", threadStore)
	newList := &TypeList{
		Addr:        addr,
		ThreadStore: threadStore,
		List:        list}

	store.AddTypeDefaultInstanceStore(threadStore, "List", addr, newList)
	return addr
}
